package com.kuaiyin.util;

import com.opencsv.CSVReader;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.FileReader;
import java.util.*;

@Slf4j
public class JtlParserUtil {

    public static class ReportSummary {
        public int totalCount;
        public int successCount;
        public int failCount;
        public double avgElapsed;
        public long minElapsed;
        public long maxElapsed;
        public double tps;
        public long p90;
        public long p95;

        @Override
        public String toString() {
            return "总数=" + totalCount +
                    " 成功=" + successCount +
                    " 失败=" + failCount +
                    " 平均耗时=" + String.format("%.2f", avgElapsed) + "ms" +
                    " 最快=" + minElapsed + "ms" +
                    " 最慢=" + maxElapsed + "ms" +
                    " P90=" + p90 + "ms" +
                    " P95=" + p95 + "ms" +
                    " TPS=" + String.format("%.2f", tps) + "/s";
        }
    }
    /*
    *   解析JTL文件
    * */
    public static Map<String, Object> parseJtl(File jtlFile) throws Exception {
        List<Long> elapsedList = new ArrayList<>();
        List<Long> timeStamps = new ArrayList<>();
        int success = 0;
        int fail = 0;
        String errorMess = "";

        boolean hasTransaction = false;
        List<String[]> allLines = new ArrayList<>();

        try (CSVReader reader = new CSVReader(new FileReader(jtlFile))) {
            String[] line;
            while ((line = reader.readNext()) != null) {
                if (line.length < 7) {
                    log.warn("行长度不足，跳过: {}", String.join(",", line));
                    continue;
                }
                allLines.add(line);

                // 判断是否包含事务控制器
                String label = line[2].trim();
                if (label.contains("事务控制器")) {
                    hasTransaction = true;
                }
            }
        }

           // 遍历所有数据行，解析并统计性能指标
        for (String[] line : allLines) {
            try {
                String label = line[2].trim();
                // 如果需要过滤事务控制器，则跳过不包含"事务控制器"标签的行
                if (hasTransaction && !label.contains("事务控制器")) {
                    continue; // 跳过非事务控制器的行
                }
                // 解析时间戳、耗时和成功状态等关键性能数据
                long timestamp = Long.parseLong(line[0].trim());
                long elapsed = Long.parseLong(line[1].trim());
                boolean isSuccess = Boolean.parseBoolean(line[7].trim());
                errorMess = line[4].trim();
                elapsedList.add(elapsed);
                timeStamps.add(timestamp);

                // 统计成功和失败的请求数量
                if (isSuccess) success++;
                else fail++;
            } catch (Exception e) {
                log.warn("解析行异常，跳过: {}，错误: {}", String.join(",", line), e.getMessage());
            }
        }


        // 计算总请求数和平均耗时
        int total = success + fail;
        double avg = elapsedList.stream().mapToLong(Long::longValue).average().orElse(0);

        // 计算时间跨度和TPS
        long minTs = timeStamps.stream().mapToLong(Long::longValue).min().orElse(0);
        long maxTs = timeStamps.stream().mapToLong(Long::longValue).max().orElse(0);
        double seconds = (maxTs - minTs) / 1000.0;
        double tps = seconds > 0 ? total / seconds : 0;

        // 计算最小和最大耗时
        long minElapsed = elapsedList.stream().mapToLong(Long::longValue).min().orElse(0);
        long maxElapsed = elapsedList.stream().mapToLong(Long::longValue).max().orElse(0);

        // 计算P90和P95耗时
        Collections.sort(elapsedList);
        long p90 = getPercentile(elapsedList, 90);
        long p95 = getPercentile(elapsedList, 95);


        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("totalCount", total);
        resultMap.put("successCount", success);
        resultMap.put("failCount", fail);
        resultMap.put("avgElapsed", String.format("%.2f", avg) + "ms");
        resultMap.put("minElapsed", minElapsed);
        resultMap.put("maxElapsed", maxElapsed);
        resultMap.put("tps", String.format("%.2f", tps) + "/s");
        resultMap.put("p90", p90);
        resultMap.put("errorMess", errorMess);
        log.info("获取计划 {} ",  errorMess);
        resultMap.put("p95", p95);
        return resultMap;
    }

    /**
     * 计算排序列表中指定百分位数的值
     *
     * @param sortedList 已排序的长整型列表，用于计算百分位数
     * @param percentile 要计算的百分位数，取值范围为0-100
     * @return 指定百分位数对应的值，如果列表为空则返回0
     */
    private static long getPercentile(List<Long> sortedList, double percentile) {
        // 处理空列表的边界情况
        if (sortedList.isEmpty()) return 0;
        // 根据百分位数计算对应的索引位置
        int index = (int) Math.ceil(percentile / 100.0 * sortedList.size()) - 1;
        // 确保索引在有效范围内
        index = Math.max(0, Math.min(index, sortedList.size() - 1));
        // 返回指定索引位置的值
        return sortedList.get(index);
    }

}
